﻿using CorpStore.Common;
using CorpStore.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.UI.StartScreen;

namespace CorpStore.ViewModels
{
    /// <summary>
    /// This is the view model for the GroupDetailsPage
    /// </summary>
    class GroupDetailsViewModel : BaseViewModel
    {
        /// <summary>
        /// Group currently being viewed on GroupDetails page
        /// </summary>
        PackageInfoGroup currentGroup;
        public PackageInfoGroup CurrentGroup
        {
            get { return currentGroup; }
            set { currentGroup = value; OnPropertyChanged(); }
        }


        // true when the progress ring should be showing
        private bool progressIsActive;
        public bool ProgressIsActive
        {
            get { return progressIsActive; }
            set { progressIsActive = value; OnPropertyChanged("ProgressIsActive"); }
        }


        public string CorpStoreTitle
        {
            get
            {
                return App.StoreTitle;
            }
        }



        /// <summary>
        /// Saves the current state of this viewModel so that it can be restored after suspension/termination
        /// </summary>
        /// <param name="pageState"></param>
        public void SaveState(ref Dictionary<string, object> pageState)
        {
            if (currentGroup != null)
                pageState["currentGroup"] = JsonConvert.SerializeObject(CurrentGroup);
            else
                pageState["currentGroup"] = "";
        }


        /// <summary>
        /// This function should be called after the GroupDetails page has been loaded
        /// </summary>
        /// <param name="serializedNavData"></param>
        /// <param name="pageState"></param>
        /// <returns></returns>
        public async Task<bool> InitOrRestoreStateAsync(string serializedNavData, Dictionary<string, object> pageState)
        {
            bool blnOK = false;

            if (pageState != null)
            {
                // we are being restored - handle it
                if (pageState.ContainsKey("currentGroup"))
                {
                    CurrentGroup = JsonConvert.DeserializeObject<PackageInfoGroup>(pageState["currentGroup"].ToString());
                    logInfo("Deserialized currentGroup object OK");
                }
            }
            else
                // no current group was passed to us - we must look it up by group name 
                await initFromNavDataAsync(serializedNavData);

            return blnOK;
        }


        /// <summary>
        /// This method will attempt to restore the state of the AppDetails page based on 
        /// the serialized data contained in 'serializedData'.  It is assumed that this
        /// serialized data is actually a serialized version of NavData.
        /// </summary>
        /// <param name="serializedData"></param>
        /// <returns></returns>
        private async Task<bool> initFromNavDataAsync(string serializedData)
        {
            bool blnOK = false;
            string errStr;

            logInfo("Attempting to deserialize navData");
            NavData navData = NavData.Deserialize(serializedData, out errStr);
            if (navData != null)
            {
                // we were able to deserialize the data - check the contents of navData out
                logInfo("Deserialized navData OK; groupName = '{0}', currentGroup is {1}", navData.ActiveGroupName, navData.CurrentGroup == null ? "null" : "provided");
                if (navData.CurrentGroup != null)
                {
                    // we were passed a currentGroup already - just use it
                    CurrentGroup = navData.CurrentGroup;
                    blnOK = true;
                    logInfo("Set CurrentGroup to navData.CurrentGroup OK");
                }
                else
                {
                    PackageInfoGroup group;
                    logInfo("Attempting to find group with a group Name of '{0}' in init", navData.ActiveGroupName);
                    group = await findCurrentGroupAsync(navData.ActiveGroupName);
                    if (group != null)
                    {
                        CurrentGroup = group;
                        blnOK = true;
                        logInfo("Found group with group Name '{0}' OK - setting CurrentGroup equal to it", navData.ActiveGroupName);
                    }
                }
            }
            else
                if (!string.IsNullOrEmpty(serializedData))
                    logErr("Error deserializing navData '{0}': {1}", serializedData, errStr);

            return blnOK;
        }


        public List<PackageInfo> GetAppsByName(string nameSubstring)
        {
            return CurrentGroup.Applications.Where(a => a.DisplayName.IndexOf(nameSubstring, StringComparison.OrdinalIgnoreCase) != -1).ToList<PackageInfo>();
        }


        public async Task RefreshCurrentGroupAsync()
        {
            currentGroup = await findCurrentGroupAsync(currentGroup.Name);
        }

        private async Task<PackageInfoGroup> findCurrentGroupAsync(string groupName)
        {
            // first load master catalog
            logInfo("Attempting to load all applications from MasterCatalog.json...");
            PackageInfoGroupList groupList = await PackageIO.LoadApplicationGroupsAsync();

            PackageInfoGroup foundGroup = groupList.Groups.Where(g => g.Name.Equals(groupName, StringComparison.OrdinalIgnoreCase)).FirstOrDefault();
            return foundGroup;
        }


        private void logErr(string msg, params object[] p)
        {
            App.LogErr(msg, p);
        }

        private void logErrWithMsg(string msg, params object[] p)
        {
            App.LogErrWithMsg(msg, p);
        }

        private void logInfo(string msg, params object[] p)
        {
            App.LogInfo(msg, p);
        }

    }
}
